import re
import json
import logging
import urllib.parse
from collections import namedtuple
from apiRequestsBase import HttpRequest, ignored
from netEaseEncode import encrypted_request, hashlib

logger = logging.getLogger(__name__)
SongInfo = namedtuple(
    'SongInfo', ['music_id', 'url', 'author', 'time', 'name', 'music_img', 'lyric'])


class NetEaseWebApi(HttpRequest):
    cookies = {
        'appver': '2.1.2.184499',
        'os': 'pc',
        'channel': 'netease',
    }
    default_timeout = 10

    def __init__(self):
        super(NetEaseWebApi, self).__init__()
        self.headers['Host'] = 'music.163.com'
        self.headers['Referer'] = 'http://music.163.com'
        self.headers['Content-Type'] = 'application/x-www-form-urlencoded'
        self.vertifyHeaders = self.headers.copy()
        self.vertifyHeaders['Host'] = 'ac.dun.163yun.com'
        self.vertifyHeaders['Accept'] = 'image/png,image/*;q=0.8,*/*;q=0.5'
        self.vertifyHeaders['Content-Type'] = ''
        self.urlEamilHeaders = self.headers.copy()
        self.urlEamilHeaders['Referer'] = ''
        self.urlEamilHeaders['Origin'] = 'orpheus://orpheus'

    def httpRequest(self, *args, **kwargs):
        data = kwargs.get('data')
        if data:
            kwargs['data'] = encrypted_request(data)
        logger.info("进行网易云Url请求, args: {0}, kwargs: {1}".format(args, kwargs))
        html = super(NetEaseWebApi, self).httpRequest(*args, **kwargs)

        with ignored():
            return json.loads(html.text)
        logger.info("url: {0} 请求失败. Header: {1}".format(
            args[0], kwargs.get('headers')))
        return False

    def login(self, username, password):
        password = password.encode()
        md5 = hashlib.md5()
        md5.update(password)
        password = md5.hexdigest()
        data = {'password': password, 'rememberLogin': 'true'}
        email = True if '@' in username else False
        if email:
            data['username'] = username
            data['clientToken'] = "1_ZfeoJYpgEKaPdueAuHxAz56XkZ28JiOG_SrSyeuuSjQrobJdGvXFN2Jo4fzHb+oRQ"
        else:
            data['phone'] = username
        urlEmail = 'http://music.163.com/weapi/login?csrf_token='
        urlPhone = 'http://music.163.com/weapi/login/cellphone?csrf_token='
        url = urlEmail if email else urlPhone
        html = self.httpRequest(url, method='POST', data=data)
        return html

    def user_playlist(self, uid, offset=0, limit=1000):
        data = {'offset': offset, 'uid': uid, 'limit': limit, 'csrf_token': ''}
        url = 'http://music.163.com/weapi/user/playlist'
        html = self.httpRequest(url, method='POST', data=data)
        try:
            return html['playlist']
        except:
            return {}

    def all_playlist(self, cat='全部歌单', types='all', offset=0, index=1):
        url = 'http://music.163.com/api/playlist/list?cat=%s&type=%s&order=%s&offset=%d&total=true&limit=30&index=%d' \
              % (urllib.parse.quote(cat), types, types, offset, index)
        html = self.httpRequest(url, method='GET', cookies=self.cookies)
        try:
            return html['playlists']
        except:
            return {}

    def details_playlist(self, ids):
        url = 'http://music.163.com/api/playlist/detail?id={0}'.format(ids)
        html = self.httpRequest(url, method="GET", cookies=self.cookies)
        with ignored():
            return html['result']
        return False

    def search(self, s, offset=0, limit=100, stype=1):
        url = 'http://music.163.com/weapi/cloudsearch/get/web'
        data = {
            's': s,
            'offset': str(offset),
            'limit': str(limit),
            'type': str(stype)
        }
        html = self.httpRequest(url, method='POST', data=data)
        try:
            return html['result']
        except:
            return {'songCount': 0, 'songs': []}

    def singsUrl(self, ids: list):
        data = {'csrf_token': '', 'ids': ids, 'br': 999000}
        url = "http://music.163.com/weapi/song/enhance/player/url"
        html = self.httpRequest(url, method='POST', data=data)
        with ignored():
            return html['data']
        logger.info('歌曲请求失败: ids {0}'.format(ids))
        return False

    def newsong(self, areaID=0, offset=0, total='true', limit=100):
        url = 'http://music.163.com/api/discovery/new/songs?areaId=%d&offset=%d&total=%s&limit=%d' % \
              (areaID, offset, total, limit)
        html = self.httpRequest(url, method='GET', cookies=self.cookies)
        return html['data']

    def fnewsong(self, year=2015, month=4, area='ALL'):
        url = 'http://music.163.com/api/discovery/new/albums/area?year=%d&month=%d&area=%s&type=hot&offset=0&total=true&limit=20&rcmd=true' \
              % (year, month, area)
        html = self.httpRequest(url, method="GET", cookies=self.cookies)
        return html['monthData']

    def lyric(self, ids):
        url = 'http://music.163.com/api/song/lyric?os=osx&id={0}&lv=-1&kv=-1&tv=-1'.format(
            ids)
        html = self.httpRequest(url, method='GET')
        try:
            return html['lrc']['lyric']
        except:
            return False

    def getContainedPlaylists(self, songId) -> set:
        rawHtml = super().httpRequest(
            'http://music.163.com/song?id={}'.format(songId), method='GET')
        containedUl = re.findall(
            r'<ul class="m-rctlist f-cb">[.\s\S]+?</ul>', rawHtml.text)
        if not containedUl:
            containedUl = ''
        else:
            containedUl = containedUl[0]
        playlists = set(re.findall(r'data-res-id="(.+)"', containedUl))
        return playlists

    def getRandomSongFromPlaylist(self, playlistId) -> list:
        allSong = self.details_playlist(playlistId)
        if allSong:
            tracks = allSong['tracks']
            SongInfoList = []
            for i in tracks:
                songInfo = SongInfo(music_id=i['id'],
                                    music_img=i['album']['blurPicUrl'],
                                    url="http(0)",
                                    lyric=None,
                                    time=i['duration'],
                                    name=i['name'],
                                    author='-'.join([x['name']
                                                     for x in i['artists']])
                                    )
                SongInfoList.append(songInfo)
            return SongInfoList
        return False


netease = NetEaseWebApi()

if __name__ == '__main__':
    help(netease)
